//! 布尔类型(真伪)和无(Null)类型实现
//!
//! 设计原则：
//! - 布尔类型：表示真值，支持逻辑运算和条件判断
//! - 无类型：表示空值或缺失值，用于初始化变量和函数返回值

use crate::interpreter::method::{Method, MethodType};
use crate::interpreter::value::{Value, ValueData};
use std::collections::HashMap;

/// 布尔类型(真伪)的方法实现
pub struct BooleanMethods;

impl BooleanMethods {
    /// 创建布尔类型的所有内置方法
    pub fn create_all_methods() -> HashMap<String, Method> {
        let mut methods = HashMap::new();

        // 基本逻辑运算方法
        methods.insert("与".to_string(), Self::create_and_method());
        methods.insert("或".to_string(), Self::create_or_method());
        methods.insert("非".to_string(), Self::create_not_method());
        methods.insert("异或".to_string(), Self::create_xor_method());

        // 比较方法
        methods.insert("等于".to_string(), Self::create_equals_method());
        methods.insert("不等于".to_string(), Self::create_not_equals_method());

        // 转换方法
        methods.insert("转字符串".to_string(), Self::create_to_string_method());
        methods.insert("转数字".to_string(), Self::create_to_number_method());
        methods.insert("转整数".to_string(), Self::create_to_integer_method());

        // 条件方法
        methods.insert("如果".to_string(), Self::create_if_method());
        methods.insert("选择".to_string(), Self::create_select_method());

        // 信息方法
        methods.insert("类型".to_string(), Self::create_type_method());
        methods.insert("描述".to_string(), Self::create_description_method());

        methods
    }

    /// 创建与运算方法
    fn create_and_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Boolean(b1), ValueData::Boolean(b2)) = (&args[0].data, &args[1].data)
            {
                Ok(Value::boolean(*b1 && *b2))
            } else {
                Err("与运算需要两个布尔值".to_string())
            }
        })
    }

    /// 创建或运算方法
    fn create_or_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Boolean(b1), ValueData::Boolean(b2)) = (&args[0].data, &args[1].data)
            {
                Ok(Value::boolean(*b1 || *b2))
            } else {
                Err("或运算需要两个布尔值".to_string())
            }
        })
    }

    /// 创建非运算方法
    fn create_not_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Boolean(b) = &args[0].data {
                Ok(Value::boolean(!*b))
            } else {
                Err("非运算需要一个布尔值".to_string())
            }
        })
    }

    /// 创建异或运算方法
    fn create_xor_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Boolean(b1), ValueData::Boolean(b2)) = (&args[0].data, &args[1].data)
            {
                Ok(Value::boolean(*b1 != *b2))
            } else {
                Err("异或运算需要两个布尔值".to_string())
            }
        })
    }

    /// 创建等于方法
    fn create_equals_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Boolean(b1), ValueData::Boolean(b2)) = (&args[0].data, &args[1].data)
            {
                Ok(Value::boolean(*b1 == *b2))
            } else {
                Err("等于比较需要两个布尔值".to_string())
            }
        })
    }

    /// 创建不等于方法
    fn create_not_equals_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let (ValueData::Boolean(b1), ValueData::Boolean(b2)) = (&args[0].data, &args[1].data)
            {
                Ok(Value::boolean(*b1 != *b2))
            } else {
                Err("不等于比较需要两个布尔值".to_string())
            }
        })
    }

    /// 创建转字符串方法
    fn create_to_string_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Boolean(b) = &args[0].data {
                let result = if *b { "真" } else { "假" };
                Ok(Value::string(result.to_string()))
            } else {
                Err("转字符串需要一个布尔值".to_string())
            }
        })
    }

    /// 创建转数字方法
    fn create_to_number_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Boolean(b) = &args[0].data {
                Ok(Value::number(if *b { 1.0 } else { 0.0 }))
            } else {
                Err("转数字需要一个布尔值".to_string())
            }
        })
    }

    /// 创建转整数方法
    fn create_to_integer_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Boolean(b) = &args[0].data {
                Ok(Value::number(if *b { 1.0 } else { 0.0 }))
            } else {
                Err("转整数需要一个布尔值".to_string())
            }
        })
    }

    /// 创建如果方法（条件执行）
    fn create_if_method() -> Method {
        Method::native(MethodType::Any, |args| {
            if let ValueData::Boolean(condition) = &args[0].data {
                if args.len() < 2 {
                    return Err("如果方法需要至少两个参数".to_string());
                }

                if *condition {
                    Ok(args[1].clone()) // 返回真值时的结果
                } else if args.len() >= 3 {
                    Ok(args[2].clone()) // 返回假值时的结果
                } else {
                    Ok(Value::null()) // 默认返回null
                }
            } else {
                Err("如果方法需要布尔值作为条件".to_string())
            }
        })
    }

    /// 创建选择方法（类似三元运算符）
    fn create_select_method() -> Method {
        Method::native(MethodType::Any, |args| {
            if let ValueData::Boolean(condition) = &args[0].data {
                if args.len() < 3 {
                    return Err("选择方法需要三个参数".to_string());
                }

                if *condition {
                    Ok(args[1].clone()) // 真值时返回第一个值
                } else {
                    Ok(args[2].clone()) // 假值时返回第二个值
                }
            } else {
                Err("选择方法需要布尔值作为条件".to_string())
            }
        })
    }

    /// 创建类型方法
    fn create_type_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Boolean(_) = &args[0].data {
                Ok(Value::string("真伪".to_string()))
            } else {
                Err("类型方法需要一个布尔值".to_string())
            }
        })
    }

    /// 创建描述方法
    fn create_description_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Boolean(b) = &args[0].data {
                let desc = if *b {
                    "布尔值真，表示条件成立或逻辑为真"
                } else {
                    "布尔值假，表示条件不成立或逻辑为假"
                };
                Ok(Value::string(desc.to_string()))
            } else {
                Err("描述方法需要一个布尔值".to_string())
            }
        })
    }
}

/// 无(Null)类型的方法实现
pub struct NullMethods;

impl NullMethods {
    /// 创建无类型的所有内置方法
    pub fn create_all_methods() -> HashMap<String, Method> {
        let mut methods = HashMap::new();

        // 基本检查方法
        methods.insert("是无".to_string(), Self::create_is_null_method());
        methods.insert("非无".to_string(), Self::create_is_not_null_method());

        // 默认值方法
        methods.insert("或默认值".to_string(), Self::create_or_default_method());
        methods.insert("或".to_string(), Self::create_or_method());

        // 转换方法
        methods.insert("转字符串".to_string(), Self::create_to_string_method());
        methods.insert("转数字".to_string(), Self::create_to_number_method());
        methods.insert("转布尔".to_string(), Self::create_to_boolean_method());
        methods.insert("转列表".to_string(), Self::create_to_list_method());
        methods.insert("转字典".to_string(), Self::create_to_dict_method());

        // 信息方法
        methods.insert("类型".to_string(), Self::create_type_method());
        methods.insert("描述".to_string(), Self::create_description_method());

        // 实用方法
        methods.insert("比较".to_string(), Self::create_compare_method());
        methods.insert("相等".to_string(), Self::create_equals_method());

        methods
    }

    /// 创建是无方法
    fn create_is_null_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::boolean(true))
            } else {
                Err("是无方法需要无值".to_string())
            }
        })
    }

    /// 创建非无方法
    fn create_is_not_null_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::boolean(false))
            } else {
                Err("非无方法需要无值".to_string())
            }
        })
    }

    /// 创建或默认值方法（如果为null则返回默认值）
    fn create_or_default_method() -> Method {
        Method::native(MethodType::Any, |args| {
            if let ValueData::Null = &args[0].data {
                if args.len() < 2 {
                    return Err("或默认值方法需要默认值参数".to_string());
                }
                Ok(args[1].clone()) // 返回默认值
            } else {
                Err("或默认值方法需要无值作为第一个参数".to_string())
            }
        })
    }

    /// 创建或方法（逻辑或，如果为null则返回第二个值）
    fn create_or_method() -> Method {
        Method::native(MethodType::Any, |args| {
            if let ValueData::Null = &args[0].data {
                if args.len() < 2 {
                    return Err("或方法需要第二个参数".to_string());
                }
                Ok(args[1].clone()) // 返回第二个值
            } else {
                Err("或方法需要无值作为第一个参数".to_string())
            }
        })
    }

    /// 创建转字符串方法
    fn create_to_string_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::string("无".to_string()))
            } else {
                Err("转字符串需要无值".to_string())
            }
        })
    }

    /// 创建转数字方法
    fn create_to_number_method() -> Method {
        Method::native(MethodType::Number, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::number(0.0))
            } else {
                Err("转数字需要无值".to_string())
            }
        })
    }

    /// 创建转布尔方法
    fn create_to_boolean_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::boolean(false))
            } else {
                Err("转布尔需要无值".to_string())
            }
        })
    }

    /// 创建转列表方法
    fn create_to_list_method() -> Method {
        Method::native(MethodType::List, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::list(vec![])) // 返回空列表
            } else {
                Err("转列表需要无值".to_string())
            }
        })
    }

    /// 创建转字典方法
    fn create_to_dict_method() -> Method {
        Method::native(MethodType::Dict, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::dict(HashMap::new())) // 返回空字典
            } else {
                Err("转字典需要无值".to_string())
            }
        })
    }

    /// 创建类型方法
    fn create_type_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::string("无".to_string()))
            } else {
                Err("类型方法需要无值".to_string())
            }
        })
    }

    /// 创建描述方法
    fn create_description_method() -> Method {
        Method::native(MethodType::String, |args| {
            if let ValueData::Null = &args[0].data {
                Ok(Value::string("空值，表示缺失或未定义的值".to_string()))
            } else {
                Err("描述方法需要无值".to_string())
            }
        })
    }

    /// 创建比较方法（null与任何值比较都为false）
    fn create_compare_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Null = &args[0].data {
                // null与任何值比较都为false
                Ok(Value::boolean(false))
            } else {
                Err("比较方法需要无值".to_string())
            }
        })
    }

    /// 创建相等方法（只有null等于null）
    fn create_equals_method() -> Method {
        Method::native(MethodType::Boolean, |args| {
            if let ValueData::Null = &args[0].data {
                // 检查第二个参数是否也是null
                if let ValueData::Null = &args[1].data {
                    Ok(Value::boolean(true))
                } else {
                    Ok(Value::boolean(false))
                }
            } else {
                Err("相等方法需要无值作为第一个参数".to_string())
            }
        })
    }
}

/// 布尔值工具函数
pub struct BooleanUtils;

impl BooleanUtils {
    /// 将任意值转换为布尔值
    pub fn to_boolean(value: &Value) -> bool {
        match &value.data {
            ValueData::Boolean(b) => *b,
            ValueData::Null => false,              // null为false
            ValueData::Number(n) => *n != 0.0,     // 非零数字为true
            ValueData::String(s) => !s.is_empty(), // 非空字符串为true
            ValueData::List(list) => !list.borrow().is_empty(), // 非空列表为true
            ValueData::Dict(dict) => !dict.borrow().is_empty(), // 非空字典为true
            ValueData::Set(set) => !set.borrow().is_empty(), // 非空集合为true
            ValueData::Tuple(tuple) => !tuple.is_empty(), // 非空元组为true
            ValueData::Closure(_) => true, // 闭包为true
            ValueData::Function { .. } => true,        // 函数为true
            ValueData::Object(_) => true,          // 对象为true
        }
    }

    /// 检查值是否为真值
    pub fn is_truthy(value: &Value) -> bool {
        Self::to_boolean(value)
    }

    /// 检查值是否为假值
    pub fn is_falsy(value: &Value) -> bool {
        !Self::to_boolean(value)
    }

    /// 检查值是否为null
    pub fn is_null(value: &Value) -> bool {
        matches!(&value.data, ValueData::Null)
    }

    /// 检查值是否不为null
    pub fn is_not_null(value: &Value) -> bool {
        !Self::is_null(value)
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_boolean_methods_creation() {
        let methods = BooleanMethods::create_all_methods();

        // 检查基本逻辑运算方法是否存在
        assert!(methods.contains_key("与"));
        assert!(methods.contains_key("或"));
        assert!(methods.contains_key("非"));
        assert!(methods.contains_key("异或"));

        // 检查比较方法是否存在
        assert!(methods.contains_key("等于"));
        assert!(methods.contains_key("不等于"));

        // 检查转换方法是否存在
        assert!(methods.contains_key("转字符串"));
        assert!(methods.contains_key("转数字"));
        assert!(methods.contains_key("转整数"));

        // 检查条件方法是否存在
        assert!(methods.contains_key("如果"));
        assert!(methods.contains_key("选择"));

        // 检查信息方法是否存在
        assert!(methods.contains_key("类型"));
        assert!(methods.contains_key("描述"));
    }

    #[test]
    fn test_null_methods_creation() {
        let methods = NullMethods::create_all_methods();

        // 检查基本检查方法是否存在
        assert!(methods.contains_key("是无"));
        assert!(methods.contains_key("非无"));

        // 检查默认值方法是否存在
        assert!(methods.contains_key("或默认值"));
        assert!(methods.contains_key("或"));

        // 检查转换方法是否存在
        assert!(methods.contains_key("转字符串"));
        assert!(methods.contains_key("转数字"));
        assert!(methods.contains_key("转布尔"));
        assert!(methods.contains_key("转列表"));
        assert!(methods.contains_key("转字典"));

        // 检查信息方法是否存在
        assert!(methods.contains_key("类型"));
        assert!(methods.contains_key("描述"));

        // 检查实用方法是否存在
        assert!(methods.contains_key("比较"));
        assert!(methods.contains_key("相等"));
    }

    #[test]
    fn test_boolean_utils() {
        // 测试真值转换
        assert!(BooleanUtils::to_boolean(&Value::boolean(true)));
        assert!(!BooleanUtils::to_boolean(&Value::boolean(false)));

        // 测试null转换
        assert!(!BooleanUtils::to_boolean(&Value::null()));

        // 测试数字转换
        assert!(BooleanUtils::to_boolean(&Value::number(1.0)));
        assert!(!BooleanUtils::to_boolean(&Value::number(0.0)));

        // 测试字符串转换
        assert!(BooleanUtils::to_boolean(&Value::string(
            "hello".to_string()
        )));
        assert!(!BooleanUtils::to_boolean(&Value::string("".to_string())));

        // 测试集合转换
        assert!(BooleanUtils::to_boolean(&Value::list(vec![Value::number(
            1.0
        )])));
        assert!(!BooleanUtils::to_boolean(&Value::list(vec![])));

        // 测试null检查
        assert!(BooleanUtils::is_null(&Value::null()));
        assert!(!BooleanUtils::is_null(&Value::boolean(true)));
    }
}
